'''
Created on Aug 19, 2012

@author: levilucio
'''
import unittest
import abstract_syntax
import abstract_syntax_exceptions


class Test(unittest.TestCase):

    def test_is_metamodel(self):
        """ should be a correct metamodel """
        v1 = {'a' : 'A', 'b' : 'B', 'c' : 'C', 'd' : 'D'}
        e1 = [('a', 'b', 'containment'),
              ('c', 'd', 'reference')]
        mm = abstract_syntax.Metamodel(v1, e1)        
#        mm.printargs()        
#        f = open('/Users/levilucio/desktop/metamodel.dot', 'w')
#        f.write('digraph myGraph {\n')
#        mm.export_dot(f)
#        f.write('}')
#        f.close()           

    def test_is_not_metamodel(self):
        """ should raise an exception because the graph is not a metamodel 
        given there is no bijection between the graph nodes and their types"""
        v1 = {'a' : 'A', 'b' : 'B', 'c' : 'A', 'd' : 'D'}
        e1 = [('a', 'b', 'containment'),
              ('c', 'd', 'reference')]   
        self.assertRaises(abstract_syntax_exceptions.NotBijectiveMetamodelError, abstract_syntax.Metamodel, v1, e1)      
        
    def test_is_model(self):
        """ should be a correct model """
        v1 = {'a' : 'A', 'b' : 'B', 'c' : 'A', 'd' : 'B'}
        e1 = [('a', 'b', 'containment'),
              ('c', 'd', 'reference')]
        v2 = {'a' : 'A', 'b' : 'B', 'c' : 'C', 'd' : 'D'}
        e2 = [('a', 'b', 'containment'),
              ('c', 'd', 'reference')]
        mm = abstract_syntax.Metamodel(v2, e2)
        m = abstract_syntax.Model(v1, e1, mm)
#        m.printargs()   
#        f = open('/Users/levilucio/desktop/model.dot', 'w')
#        f.write('digraph myGraph {\n')
#        m.export_dot(f)
#        f.write('}')
#        f.close()  

    def test_model_does_not_conforms(self):
        """ should raise an exception because the model does not conform
        to its' metamodel """
        v1 = {'a' : 'A', 'b' : 'B', 'c' : 'A', 'd' : 'D'}
        e1 = [('a', 'b', 'containment'),
              ('c', 'd', 'reference')]
        v2 = {'a' : 'A', 'b' : 'B', 'c' : 'C', 'd' : 'D'}
        e2 = [('a', 'b', 'containment'),
              ('c', 'd', 'reference')]
        mm = abstract_syntax.Metamodel(v2, e2)   
        self.assertRaises(abstract_syntax_exceptions.ModelDoesNotConform, abstract_syntax.Model, v1, e1, mm)
        
    def test_is_indirect_model(self):
        """ should be a correct indirect model """
        v = {'a' : 'A', 'b' : 'B', 'c' : 'A', 'd' : 'D'}
        e = [('a', 'b', 'containment'),
             ('b', 'd', 'reference'),
             ('b', 'c', 'containment')]
        il = [('a', 'c'), ('a', 'b')]
        vmm = {'a' : 'A', 'b' : 'B', 'd' : 'D'}
        emm = [('a', 'b', 'containment'),
               ('b', 'a', 'reference'),
               ('b', 'd', 'containment')]
        mm = abstract_syntax.Metamodel(vmm, emm)
        im = abstract_syntax.IndirectModel(v, e, il, mm)
#        im.printargs()        
#        f = open('/Users/levilucio/desktop/indirect_model.dot', 'w')
#        f.write('digraph myGraph {\n')
#        im.export_dot(f)
#        f.write('}')
#        f.close()         

    def test_is_match_apply_model(self):
        """ should be a correct match apply model"""
        v1 = {'a' : 'A', 'b' : 'B', 'c' : 'A', 'd' : 'B'}
        e1 = [('a', 'b', 'containment'),
              ('c', 'd', 'reference')]
        v2 = {'e' : 'C', 'f' : 'D'}
        e2 = [('e', 'f', 'containment')]
        vmm = {'a' : 'A', 'b' : 'B', 'c' : 'C', 'd' : 'D'}
        emm = [('a', 'b', 'containment'),
              ('c', 'd', 'reference')]
        mm = abstract_syntax.Metamodel(vmm, emm)
        m1 = abstract_syntax.Model(v1, e1, mm)
        m2 = abstract_syntax.Model(v2, e2, mm)
        bl = [('a', 'e'), ('c', 'e')]
        ma = abstract_syntax.MatchApplyModel(m1, m2, bl)
#        ma.printargs()
#        f = open('/Users/levilucio/desktop/match_apply_model.dot', 'w')
#        f.write('digraph myGraph {\n')
#        ma.export_dot(f)
#        f.write('}')
#        f.close()       

    def test_backward_links_not_sound_in_match_apply_model(self):
        """ should not be a correct match apply model """
        v1 = {'a' : 'A', 'b' : 'B', 'c' : 'A', 'd' : 'B'}
        e1 = [('a', 'b', 'containment'),
              ('c', 'd', 'reference')]
        v2 = {'e' : 'C', 'f' : 'D'}
        e2 = [('e', 'f', 'containment')]
        vmm = {'a' : 'A', 'b' : 'B', 'c' : 'C', 'd' : 'D'}
        emm = [('a', 'b', 'containment'),
              ('c', 'd', 'reference')]
        mm = abstract_syntax.Metamodel(vmm, emm)
        m1 = abstract_syntax.Model(v1, e1, mm)
        m2 = abstract_syntax.Model(v2, e2, mm)
        bl = [('a', 'e'), ('c', 'a')]
        self.assertRaises(abstract_syntax_exceptions.BackwardLinksNotSound, abstract_syntax.MatchApplyModel, m1, m2, bl)         
        
    def test_repeated_vertices_in_match_apply_model(self):
        """ should be a correct match apply model """
        v1 = {'a' : 'A', 'b' : 'B', 'c' : 'A', 'd' : 'B'}
        e1 = [('a', 'b', 'containment'),
              ('c', 'd', 'reference')]
        v2 = {'a' : 'C', 'b' : 'D'}
        e2 = [('a', 'b', 'containment')]
        vmm = {'a' : 'A', 'b' : 'B', 'c' : 'C', 'd' : 'D'}
        emm = [('a', 'b', 'containment'),
              ('c', 'd', 'reference')]
        mm = abstract_syntax.Metamodel(vmm, emm)
        m1 = abstract_syntax.Model(v1, e1, mm)
        m2 = abstract_syntax.Model(v2, e2, mm)
        self.assertRaises(abstract_syntax_exceptions.NotDisjointGraphs, abstract_syntax.MatchApplyModel, m1, m2, [])
        
    def test_is_transformation_rule(self):
        """ should be a correct transformation rule"""
        v1 = {'a' : 'A', 'b' : 'B', 'c' : 'A', 'd' : 'D'}
        e1 = [('a', 'b', 'containment'),
             ('b', 'd', 'reference'),
             ('b', 'c', 'containment')]
        il1 = [('a', 'c'), ('a', 'b')]
        vmm1 = {'a' : 'A', 'b' : 'B', 'd' : 'D'}
        emm1 = [('a', 'b', 'containment'),
               ('b', 'a', 'reference'),
               ('b', 'd', 'containment')]
        mm1 = abstract_syntax.Metamodel(vmm1, emm1)                
        v2 = {'e' : 'C', 'f' : 'D'}
        e2 = [('e', 'f', 'containment')]
        vmm2 = {'a' : 'A', 'b' : 'B', 'c' : 'C', 'd' : 'D'}
        emm2 = [('a', 'b', 'containment'),
              ('c', 'd', 'reference')]
        mm2 = abstract_syntax.Metamodel(vmm2, emm2)
        m1 = abstract_syntax.IndirectModel(v1, e1, il1, mm1)
        m2 = abstract_syntax.Model(v2, e2, mm2)
        bl = [('a', 'e'), ('c', 'e')]
        tr = abstract_syntax.TransformationRule(m1, m2, bl)
#        tr.printargs()
#        f = open('/Users/levilucio/desktop/transformation_rule.dot', 'w')
#        f.write('digraph myGraph {\n')
#        tr.export_dot(f)
#        f.write('}')
#        f.close()       

    def test_is_property(self):
        """ should be a correct property"""
        v1 = {'a' : 'A', 'b' : 'B', 'c' : 'A', 'd' : 'D'}
        e1 = [('a', 'b', 'containment'),
             ('b', 'd', 'reference'),
             ('b', 'c', 'containment')]
        il1 = [('a', 'c'), ('a', 'b')]
        vmm1 = {'a' : 'A', 'b' : 'B', 'd' : 'D'}
        emm1 = [('a', 'b', 'containment'),
               ('b', 'a', 'reference'),
               ('b', 'd', 'containment')]
        mm1 = abstract_syntax.Metamodel(vmm1, emm1)                
        v2 = {'e' : 'C', 'f' : 'D'}
        e2 = [('e', 'f', 'containment')]
        il2 = [('e', 'f')]        
        vmm2 = {'a' : 'A', 'b' : 'B', 'c' : 'C', 'd' : 'D'}
        emm2 = [('a', 'b', 'containment'),
              ('c', 'd', 'reference')]
        mm2 = abstract_syntax.Metamodel(vmm2, emm2)
        m1 = abstract_syntax.IndirectModel(v1, e1, il1, mm1)
        m2 = abstract_syntax.IndirectModel(v2, e2, il2, mm2)
        bl = [('a', 'e'), ('c', 'e')]
        p = abstract_syntax.Property(m1, m2, bl)
#        p.printargs()
        f = open('/Users/levilucio/desktop/property.dot', 'w')
        f.write('digraph myGraph {\n')
        p.export_dot(f)
        f.write('}')
        f.close()  


if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.testName']
    unittest.main()
